home *** CD-ROM | disk | FTP | other *** search
/ Tech Arsenal 1 / Tech Arsenal (Arsenal Computer).ISO / tek-01 / ohlfind.zip / LISTFILE.C < prev    next >
C/C++ Source or Header  |  1990-06-25  |  6KB  |  258 lines

  1. /* listfile.c -- display a long listing of a file
  2.    Copyright (C) 1985, 1988, 1989, 1990 Free Software Foundation, Inc.
  3.  
  4.    This program is free software; you can redistribute it and/or modify
  5.    it under the terms of the GNU General Public License as published by
  6.    the Free Software Foundation; either version 1, or (at your option)
  7.    any later version.
  8.  
  9.    This program is distributed in the hope that it will be useful,
  10.    but WITHOUT ANY WARRANTY; without even the implied warranty of
  11.    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  12.    GNU General Public License for more details.
  13.  
  14.    You should have received a copy of the GNU General Public License
  15.    along with this program; if not, write to the Free Software
  16.    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.  */
  17.  
  18. #include <stdio.h>
  19. #include <sys/types.h>
  20. #include <sys/stat.h>
  21. #include <pwd.h>
  22. struct passwd *getpwuid ();
  23. #include <grp.h>
  24. struct group *getgrgid ();
  25. #include <time.h>
  26. #ifdef USG
  27. #include <sys/sysmacros.h>
  28. #include <string.h>
  29. #else
  30. #include <strings.h>
  31. #endif
  32.  
  33. extern int errno;
  34.  
  35. long time ();
  36. void free ();
  37.  
  38. char *xmalloc ();
  39. void error ();
  40. void mode_string ();
  41.  
  42. char *copystring ();
  43. char *get_link_name ();
  44. char *getgroup ();
  45. char *getuser ();
  46. void print_name_with_quoting ();
  47.  
  48. void
  49. list_file (name, statp)
  50.      char *name;
  51.      struct stat *statp;
  52. {
  53.   char modebuf[20];
  54.   char timebuf[40];
  55.   long current_time = time ((time_t *) 0);
  56.  
  57.   mode_string (statp->st_mode, modebuf);
  58.   modebuf[10] = '\0';
  59.  
  60.   strcpy (timebuf, ctime (&statp->st_mtime));
  61.   if (current_time - statp->st_mtime > 6L * 30L * 24L * 60L * 60L
  62.       || current_time - statp->st_mtime < 0L)
  63.     {
  64.       /* The file is fairly old or in the future.
  65.      POSIX says the cutoff is 6 months old;
  66.      approximate this by 6*30 days.
  67.      Show the year instead of the time of day.  */
  68.       strcpy (timebuf + 11, timebuf + 19);
  69.     }
  70.   timebuf[16] = 0;
  71.  
  72.   printf ("%6u ", statp->st_ino);
  73.  
  74.   /* The space between the mode and the number of links is the POSIX
  75.      "optional alternate access method flag". */
  76.   printf ("%s %3u ", modebuf, statp->st_nlink);
  77.  
  78.   printf ("%-8.8s ", getuser (statp->st_uid));
  79.  
  80.   printf ("%-8.8s ", getgroup (statp->st_gid));
  81.  
  82.   if ((statp->st_mode & S_IFMT) == S_IFCHR
  83.       || (statp->st_mode & S_IFMT) == S_IFBLK)
  84.     printf ("%3u, %3u ", major (statp->st_rdev), minor (statp->st_rdev));
  85.   else
  86.     printf ("%8lu ", statp->st_size);
  87.  
  88.   printf ("%s ", timebuf + 4);
  89.  
  90.   print_name_with_quoting (name);
  91.  
  92. #ifdef S_IFLNK
  93.   if ((statp->st_mode & S_IFMT) == S_IFLNK)
  94.     {
  95.       char *linkname = get_link_name (name, statp);
  96.  
  97.       if (linkname)
  98.     {
  99.       fputs (" -> ", stdout);
  100.       print_name_with_quoting (linkname);
  101.       free (linkname);
  102.     }
  103.     }
  104. #endif
  105.   putchar ('\n');
  106. }
  107.  
  108. void
  109. print_name_with_quoting (p)
  110.      register char *p;
  111. {
  112.   register unsigned char c;
  113.  
  114.   while (c = *p++)
  115.     {
  116.       switch (c)
  117.     {
  118.     case '\\':
  119.       printf ("\\\\");
  120.       break;
  121.  
  122.     case '\n':
  123.       printf ("\\n");
  124.       break;
  125.  
  126.     case '\b':
  127.       printf ("\\b");
  128.       break;
  129.  
  130.     case '\r':
  131.       printf ("\\r");
  132.       break;
  133.  
  134.     case '\t':
  135.       printf ("\\t");
  136.       break;
  137.  
  138.     case '\f':
  139.       printf ("\\f");
  140.       break;
  141.  
  142.     case ' ':
  143.       printf ("\\ ");
  144.       break;
  145.  
  146.     case '"':
  147.       printf ("\\\"");
  148.       break;
  149.  
  150.     default:
  151.       if (c > 040 && c < 0177)
  152.         putchar (c);
  153.       else
  154.         printf ("\\%03o", (unsigned int) c);
  155.     }
  156.     }
  157. }
  158.  
  159. #ifdef S_IFLNK
  160. char *
  161. get_link_name (filename, statp)
  162.      char *filename;
  163.      struct stat *statp;
  164. {
  165.   register char *linkbuf;
  166.   register int bufsiz = statp->st_size;
  167.  
  168.   linkbuf = (char *) xmalloc (bufsiz + 1);
  169.   linkbuf[bufsiz] = 0;
  170.   if (readlink (filename, linkbuf, bufsiz) < 0)
  171.     {
  172.       error (0, errno, "%s", filename);
  173.       free (linkbuf);
  174.       return 0;
  175.     }
  176.   return linkbuf;
  177. }
  178. #endif
  179.  
  180. struct userid
  181. {
  182.   int uid;
  183.   char *name;
  184.   struct userid *next;
  185. };
  186.  
  187. struct userid *user_alist;
  188.  
  189. /* Translate `uid' to a login name, with cache.  */
  190.  
  191. char *
  192. getuser (uid)
  193.      int uid;
  194. {
  195.   register struct userid *tail;
  196.   struct passwd *pwent;
  197.   char usernum_string[20];
  198.  
  199.   for (tail = user_alist; tail; tail = tail->next)
  200.     if (tail->uid == uid)
  201.       return tail->name;
  202.  
  203.   pwent = getpwuid (uid);
  204.   tail = (struct userid *) xmalloc (sizeof (struct userid));
  205.   tail->uid = uid;
  206.   tail->next = user_alist;
  207.   if (pwent == 0)
  208.     {
  209.       sprintf (usernum_string, "%u", uid);
  210.       tail->name = copystring (usernum_string);
  211.     }
  212.   else
  213.     tail->name = copystring (pwent->pw_name);
  214.   user_alist = tail;
  215.   return tail->name;
  216. }
  217.  
  218. /* We use the same struct as for userids.  */
  219. struct userid *group_alist;
  220.  
  221. /* Translate `gid' to a group name, with cache.  */
  222.  
  223. char *
  224. getgroup (gid)
  225.      int gid;
  226. {
  227.   register struct userid *tail;
  228.   struct group *grent;
  229.   char groupnum_string[20];
  230.  
  231.   for (tail = group_alist; tail; tail = tail->next)
  232.     if (tail->uid == gid)
  233.       return tail->name;
  234.  
  235.   grent = getgrgid (gid);
  236.   tail = (struct userid *) xmalloc (sizeof (struct userid));
  237.   tail->uid = gid;
  238.   tail->next = group_alist;
  239.   if (grent == 0)
  240.     {
  241.       sprintf (groupnum_string, "%u", gid);
  242.       tail->name = copystring (groupnum_string);
  243.     }
  244.   else
  245.     tail->name = copystring (grent->gr_name);
  246.   group_alist = tail;
  247.   return tail->name;
  248. }
  249.  
  250. /* Return a newly allocated copy of `string'. */
  251.  
  252. char *
  253. copystring (string)
  254.      char *string;
  255. {
  256.   return strcpy ((char *) xmalloc (strlen (string) + 1), string);
  257. }
  258.